2小时,账单47万!「Milkie Way公司破产未遂事件」复盘分析
2019年11月,Milkie Way公司开始开发一个叫Announce的产品。
2020年3月,这家初创公司就差点儿破产关门。
一个云上的小测试项目,使用了数据库和Serverless服务,几个小时,在1000个实例上进行了1160亿次读取和3300万次写入,他们不小心烧掉了将近72000 美元(折合人民币约47万元)!
EXO ME ???????
我们大概讲过一万次(bushi):用户用云是有一定的学习成本和难度的。在应用和基础架构,加上丰富多样的云产品和服务之间,是存在GAP的。
但一直没有合适的案例。
这次的「Milkie Way公司破产未遂事件」,当事人Sudeep Chauhan的一手复盘分析和经验总结,我们觉得非常有代表性和参考性,值得跟大家分享。
尽管文中的示例是关于GCP(Google Cloud Platform)的,但所有云服务都具有相似的功能,只不过具有不同的名称、价格和使用策略。
事情是怎么发生的?
作为一家初创企业,一开始团队就是简单快速创建了MVP(最小可行性产品),把产品部署在Google App引擎上。工作的重点都放在写产品代码和UI设计上,对云的关心程度仅限于“能用就行”。
这,就为后面发生的事情埋下了导火索。
2020年,随着新冠疫情的爆发,Sudeep Chauhan认为这可能是他们的产品走向世界的好机会。于是,创建了Announce-AI项目。
团队在没有彻底研究清楚Cloud Run(Serverless服务)到底是怎么个玩法的情况下就在上面部署了“测试版”Announce-AI,想看看效果怎么样。
由于这个测试版只是一个非常小的站点,所以团队选择了Firebase的数据库。
他们创建了一个新的GCP项目,设置了7美元的云资源使用预算,选择了Firebase免费计划,想着最坏不过是超过每天的免费额度(该计划免费提供5GB的存储空间,以及每天免费提供5万次读取和2万次写入操作)。
3月26日,一切都很好。
到了第二天晚上,噩梦就开始了。
Sudeep Chauhan在邮箱中发现了几封来自GCP的提醒邮件:
第一封邮件:您的Firebase Project已自动升级为收费账户。
第二封邮件:您在GCP的7美元云资源使用预算已超支。
就在他还在思考如何付清这笔“巨款”的时候,更可怕的事发生了:账单金额还在不停增长!
5 分钟后,账单显示15000美元。
20分钟后,账单显示25000美元。
…………
他整个人都懵了。
他们到底做错了什么?
他们主要犯了两方面的错:
一、在云上部署了有缺陷的算法;
二、对GCP产品和服务的认知不足,使用默认选项。
有缺陷的算法
团队使用POST请求将URL作为数据发送到某一实例,且并发使用多个实例以替代串行使用单一实例(这是发挥云上弹性优势的常见操作)。由于Cloud Run的处理操作能够精确到毫秒,所以全部页面都将得到并发处理,整体性能得到了高度优化。
但在具体的编码过程中,由于缺少break语句,实例无法中断。而POST请求可以具有相同的URL,如果其中存在指向上一页的反射链接,那么Cloud Run服务就会陷入无限递归中,而且这个递归会呈指数增长。
团队将最大实例数设置为1000,这意味着当测试开始后,这1000个实例会不断进行查询,并且每几毫秒就向Firebase数据库写入一次。高峰时,Firebase每分钟的请求数甚至高达10亿个。
24小时内,Cloud Run进入后台进程,在1000个实例上,一共消耗了16022个小时。
最终,在账户被GCP停用前,该项目共执行了1160亿次读取和3300万次写入。而Firebase上的读取成本是每十万次0.06美元,仅此项花费就接近7万美元。
不了解GCP产品和服务
1、不了解Firebase就直接用了,也没注意账户会自动升级成付费账户
Firebase不是一种可以学习的语言,是Google提供的一种Serverless服务,有特定的规则,而不是由自然法则或特定用户可能会认为的规则来定义。
而且虽然他们使用的是Firebase的免费计划,但他们并没有注意到GCP刚刚更新了和Firebase的深度集成,一旦接受了GCP项目的结算条款,Firebase账户默认可以自动升级为付费账户。
2、不知道GCP账单有延迟
团队过于依赖GCP自带的预算超支通知,由于需要先进行结算,该通知在结算完成后才会发出,当预算超支,触发云功能关闭的时候,大量账单费用已经产生了。
3、没有意识到Firebase仪表盘数据存在延迟可能造成的后果
虽然Firebase控制台文档明确表明仪表板数字和GCP账单数据略有不同。但在发生每分钟10亿次请求时,这个延迟将非常致命。
4、信用卡支付限额并不能阻止巨额账单的生成
GCP的账单结算与支付之间同样存在延迟,因此100美元的信用卡支付限额并不能阻止巨额账单的生成。当GCP发现无法扣款后,用户账号被停用,但此时已经产生了大量的欠费。
完美的故事结局
幸运的是,他们还活着。
在等待、咨询、冗长的电子邮件和查找BUG上花费了无数的时间后,Google最终免掉了他们的账单。
一般来说,故事到了这里就结束了。
就像王子和公主幸福地生活在一起了一样。
但我们更想问一句:后来呢?
后来,Milkie Way公司花了几个月的时间来了解云和自己的产品体系架构,报废了V1版的产品,构建了可扩展的架构来为产品提供动力,在云上建立了一个可以快速迭代、安全的平台,而不仅仅是一个MVP。
7个月后,他们发布了V2版产品。
去年年底,创始人Sudeep Chauhan在公司博客上复盘了这次事件,说:
“云就像一把双刃剑。如果使用得当,它可能会很有用,但是如果使用不当,则可能会导致后果。
如果您算一下GCP文档中的页数,则可能比几本小说中的页数还多。了解定价和用法不仅耗时,而且需要深入了解云服务的工作方式。
怪不得有人专门做这个!(没错,说的就是我们。)
Firebase和Cloud Run确实强大。
在高峰期,Firebase能够处理每分钟约10亿次读取。这是异常强大的。我们已经在Firebase上玩了2-3个月,并且仍在学习它,但是直到现在我仍然完全不知道它有多强大。
Cloud Run也是如此!并发==60,max_containers == 1000,每个请求占用400毫秒,Cloud Run的请求数每分钟可以处理900万个请求!60 * 1000 * 2.5 * 60 = 9,000,000个请求/分钟
相比之下,Google搜索每分钟可获得380万次搜索。“
Sudeep Chauhan的云实践一手经验
多花点时间学习
1.1、上云之前请先阅读说明书
几乎所有云产品都有非常完整且不断更新的操作指南,里面包含了一系列需要做或不应该做的事情。
强烈建议阅读即将使用的每项云服务的操作指南,这不仅能够得到帮助,也可以避免不必要的麻烦。
1.2、不要直接挑战多云HARD模式
不同的云厂商有各自不同的优缺点,如果你有专门的开发团队和SRE(就是DevOps),你可以使用多云。但如果你是独立开发人员或小型创业公司,建议你不要一上来就使用多云,除非你确实需要其他云平台的某个独有功能。
因为每个云平台都有丰富的产品类型和大量的工具资料,多花一些时间研究这些东西,可以确保你对整个云平台和即将使用的产品服务有一个清晰的认识。
我们的fastone多云平台,5分钟快速上手的可视化界面免去了大量学习成本,扫码免费试用现在还送300元体验金,了解一下?入股不亏。
1.3、了解钱是怎么花出去的
大多数云服务都会提供成本计算器,多花一些时间测试成本,确保你知道钱都花到哪里了,再开始部署。
比较可靠的做法是,先在安全的环境(开发帐户)中测试服务一到两天,等待完整帐单处理完毕,并且你能够正确理解帐单上的每一项之后,再将其集成到产品中。
我们有一份六大云厂商服务器资源价格多维度对比报告,对云上资源的灵活计费模式做了深度科普,扫码添加小F微信号(ID:imfastone)即可免费获取。
不要做这两件事
2.1、不要下载密钥
保护密钥和令牌的最简单解决方案是永远不要下载它们。
2.2、不要把鸡蛋放在一个篮子里
理想情况下,在任何项目中,你都应该具有dev、test、staging、prod环境。即便项目非常小,你也应该至少拥有相互之间完全分离的dev和prod环境。
捂紧你的钱包
3.1、设置云厂商的服务配额
大多数云服务都可以设置配额,也就是支付上限,可以从每天、每分钟、每用户每分钟使用等多个维度来进行该设置。
当你的实际使用情况达到配额上限时,平台就会自动切断服务。
在设置配额时,需要注意两点:
某些默认配额是针对大客户的,在普通用户看来会非常离谱,比如每天一百万美元的云资源预算,必须重新对其进行设置;
并非所有服务都有配额限制,比如在本次事件中起主要因素的Firebase读写操作。
3.2、强烈建议开启云监控功能
当云服务的使用情况超出用户设置的配额时,云监控可以触发包括短信、电子邮件和应用程序通知在内的警报,云监控的大多数指标仅有几分钟的延迟。
GCP把这项服务称为Cloud Monitoring,AWS叫Cloud Watch,Microsoft叫Azure Monitor,国内包括阿里云、华为云、腾讯云在内的主流云厂商均称其为云监控。
这个服务一般是免费的,或者只收取极低的价格,建议时刻开启这项服务。
3.3、设置预算超支通知
几乎所有云平台的文档都会都建议用户设置预算超支通知,但由于整个“结算-账单-通知”流程存在延迟,当你收到预算超支的通知时,你可能已经积累了相当大金额的账单,你应该开启这个功能,但不要过于依赖它。
云在提供海量资源的同时也在考验着用户的技术能力,不管是普通的云上部署/数据传输,还是高阶的弹性动态使用资源,再进一步根据用户策略的智能自动化调度,很多事情手动做和自动化做的差别很大,甚至手动根本无法完成,比如——
集群自动化部署:从4天到1.75小时,如何让Bladed仿真效率提升55倍?
基于用户策略智能调度:提速2920倍!用AutoDock Vina对接2800万个分子
GPU/CPU异构资源:155个GPU!多云场景下的Amber自由能计算
3.4、使用多种付款方式,并设置支出限额
首先,你必须给开发和生产环境分配不同的付款方式,避免两者混用。
这样当其中一个付款方式出现问题后,它只会影响其绑定的环境,而不会对其他工作产生影响。
其次,对付款方式设置支出限额,支出限额可以设置在你预计费用的120-150%之间。
我们在3.1中设置了服务配额,如果某个服务达到了这个配额,那么云平台会立即扣费,扣款会失败,你的服务会被暂停。
如果你没有对你的付款方式设置支出限额,或者你绑定的压根就是一张无限信用卡,那费用就会被成功扣除,可能会从你的卡里扣除一笔远远超过你预期的费用。
这是最后一道防线了,如果你严格按照本文中的建议操作,应该用不到这一步。
如果这些都做到了,你应该能睡个好觉。
我们有个为应用定义的云平台
集成多种应用,大量任务多节点并行
应对短时间爆发性需求,连网即用
跑任务快,原来几个月甚至几年,现在只需几小时
5分钟快速上手,拖拉点选可视化界面,无需代码
支持高级用户直接在云端创建集群
扫码免费试用,送300元体验金,入股不亏~